(*
  https://www.rfc-editor.org/rfc/rfc9421#appendix-B
*)
open Alcotest
open Seppo_lib

let set_up () =
  Unix.chdir "../../../test/"

(* https://www.rfc-editor.org/rfc/rfc9421#name-minimal-signature-using-rsa *)
let tc_b21_example_minimal_rsa () =
  (match {|sig-b21=();created=1618884473;keyid="test-key-rsa-pss";nonce="b3k2pp5k7z-50gnwp.yemd"|}
         |> Rfc9651.(parse_string ~term:sf_dictionary) with
  | Ok
      (`Sf_Dictionary
         [(("sig-b21", []),
           (`Sf_Innerlist [],
            [("created", `Sf_Integer 1618884473);
             ("keyid", `Sf_String "test-key-rsa-pss");
             ("nonce", `Sf_String "b3k2pp5k7z-50gnwp.yemd")]))],
       [])
    -> ()
  | Error s -> s |> check string __LOC__ ""
  | _ -> failwith __LOC__);
  (match {|sig-b21=:d2pmTvmbncD3xQm8E9ZV2828BjQWGgiwAaw5bAkgibUopemLJcWDy/lkbbHAve4cRAtx31Iq786U7it++wgGxbtRxf8Udx7zFZsckzXaJMkA7ChG52eSkFxykJeNqsrWH5S+oxNFlD4dzVuwe8DhTSja8xxbR/Z2cOGdCbzR72rgFWhzx2VjBqJzsPLMIQKhO4DGezXehhWwE56YCE+O6c0mKZsfxVrogUvA4HELjVKWmAvtl6UnCh8jYzuVG5WSb/QEVPnP5TmcAnLH1g+s++v6d4s8m0gCw1fV5/SITLq9mhho8K3+7EPYTU8IU1bLhdxO5Nyt8C8ssinQ98Xw9Q==:|}
         |> Rfc9651.(parse_string ~term:sf_dictionary) with
  | Ok
      (`Sf_Dictionary
         [(("sig-b21", []),
           (`Sf_Binary b , []) )],
       [])
    -> b |> Bytes.length |> check int __LOC__ 256
  | Error s -> s |> check string __LOC__ ""
  | _ -> failwith __LOC__);
  ()

(** https://www.rfc-editor.org/rfc/rfc9421#appendix-B.2.2 *)
let tc_b22 () =
  (match {|sig-b22=("@authority" "content-digest" "@query-param";name="Pet");created=1618884473;keyid="test-key-rsa-pss";tag="header-example"|}
         |> Rfc9651.(parse_string ~term:sf_dictionary) with
  |
    Ok
      (`Sf_Dictionary
         [(("sig-b22", []),
           (`Sf_Innerlist
              [(`Sf_String "@authority", []);
               (`Sf_String "content-digest", []);
               (`Sf_String "@query-param", [("name", `Sf_String "Pet")])],
            [("created", `Sf_Integer 1618884473);
             ("keyid", `Sf_String "test-key-rsa-pss");
             ("tag", `Sf_String "header-example")]))],
       [])
    -> ()
  | Error s -> s |> check string __LOC__ ""
  | _ -> failwith __LOC__);
  (match {|sig-b22=:LjbtqUbfmvjj5C5kr1Ugj4PmLYvx9wVjZvD9GsTT4F7GrcQEdJzgI9qHxICagShLRiLMlAJjtq6N4CDfKtjvuJyE5qH7KT8UCMkSowOB4+ECxCmT8rtAmj/0PIXxi0A0nxKyB09RNrCQibbUjsLS/2YyFYXEu4TRJQzRw1rLEuEfY17SARYhpTlaqwZVtR8NV7+4UKkjqpcAoFqWFQh62s7Cl+H2fjBSpqfZUJcsIk4N6wiKYd4je2U/lankenQ99PZfB4jY3I5rSV2DSBVkSFsURIjYErOs0tFTQosMTAoxk//0RoKUqiYY8Bh0aaUEb0rQl3/XaVe4bXTugEjHSw==:|}
         |> Rfc9651.(parse_string ~term:sf_dictionary) with
  | Ok (`Sf_Dictionary _,_)
    -> ()
  | Error s -> s |> check string __LOC__ ""
  | _ -> failwith __LOC__);
  ()

(* https://www.rfc-editor.org/rfc/rfc9421#name-full-coverage-using-rsa-pss *)
let tc_b23 () =
  (match {|sig-b23=("date" "@method" "@path" "@query" "@authority" "content-type" "content-digest" "content-length");created=1618884473;keyid="test-key-rsa-pss"|}
         |> Rfc9651.(parse_string ~term:sf_dictionary) with
  | Ok
      (`Sf_Dictionary
         [("sig-b23", []),
          (`Sf_Innerlist
             [(`Sf_String "date", []);
              (`Sf_String "@method", []);
              (`Sf_String "@path", []);
              (`Sf_String "@query", []);
              (`Sf_String "@authority", []);
              (`Sf_String "content-type", []);
              (`Sf_String "content-digest", []);
              (`Sf_String "content-length", [])],
           [("created", `Sf_Integer 1618884473);
            ("keyid", `Sf_String "test-key-rsa-pss")])],
       [])
    -> ()
  | Error s -> s |> check string __LOC__ ""
  | _ -> failwith __LOC__);
  (match
     {|sig-b23=:bbN8oArOxYoyylQQUU6QYwrTuaxLwjAC9fbY2F6SVWvh0yBiMIRGOnMYwZ/5MR6fb0Kh1rIRASVxFkeGt683+qRpRRU5p2voTp768ZrCUb38K0fUxN0O0iC59DzYx8DFll5GmydPxSmme9v6ULbMFkl+V5B1TP/yPViV7KsLNmvKiLJH1pFkh/aYA2HXXZzNBXmIkoQoLd7YfW91kE9o/CCoC1xMy7JA1ipwvKvfrs65ldmlu9bpG6A9BmzhuzF8Eim5f8ui9eH8LZH896+QIF61ka39VBrohr9iyMUJpvRX2Zbhl5ZJzSRxpJyoEZAFL2FUo5fTIztsDZKEgM4cUA==:|}
     |> Rfc9651.(parse_string ~term:sf_dictionary) with
  | Ok
      (`Sf_Dictionary
         [(("sig-b23", []),
           (`Sf_Binary b, []))],
       [])
    -> b |> Bytes.length |> check int __LOC__ 256
  | Error s -> s |> check string __LOC__ ""
  | _ -> failwith __LOC__);
  ()

(* https://www.rfc-editor.org/rfc/rfc9421#name-signing-a-response-using-ec *)
let tc_b24 () =
  (match {|sig-b24=:wNmSUAhwb5LxtOtOpNa6W5xj067m5hFrj0XQ4fvpaCLx0NKocgPquLgyahnzDnDAUy5eCdlYUEkLIj+32oiasw==:|}
         |> Rfc9651.(parse_string ~term:sf_dictionary) with
  | Ok
      (`Sf_Dictionary
         [(("sig-b24", []),
           (`Sf_Binary b, []))],
       [])
    -> b |> Bytes.length |> check int __LOC__ 64
  | Error s -> s |> check string __LOC__ ""
  | _ -> failwith __LOC__);
  ()

(* https://www.rfc-editor.org/rfc/rfc9421#section-4.3-11 *)
let tc_4311 () =
  (match {|sig1=("@method" "@authority" "@path" "content-digest" "content-type" "content-length");created=1618884475;keyid="test-key-ecc-p256", oxy_sig=("@method" "@authority" "@path" "content-digest" "content-type" "content-length" "forwarded");created=1618884480;keyid="test-key-rsa";alg="rsa-v1_5-sha256";expires=1618884540|}
         |> Rfc9651.(parse_string ~term:sf_dictionary) with
  | Ok (`Sf_Dictionary
          [(("sig1", []),
            (`Sf_Innerlist
               [(`Sf_String "@method", []);
                (`Sf_String "@authority", []);
                (`Sf_String "@path", []);
                (`Sf_String "content-digest", []);
                (`Sf_String "content-type", []);
                (`Sf_String "content-length", [])],
             [("created", `Sf_Integer 1618884475);
              ("keyid", `Sf_String "test-key-ecc-p256")]));
           (("oxy_sig", []),
            (`Sf_Innerlist
               [(`Sf_String "@method", []);
                (`Sf_String "@authority", []);
                (`Sf_String "@path", []);
                (`Sf_String "content-digest", []);
                (`Sf_String "content-type", []);
                (`Sf_String "content-length", []);
                (`Sf_String "forwarded", [])],
             [("created", `Sf_Integer 1618884480);
              ("keyid", `Sf_String "test-key-rsa");
              ("alg", `Sf_String "rsa-v1_5-sha256");
              ("expires", `Sf_Integer 1618884540)]))],
        [])
    -> ()
  | Error s -> s |> check string __LOC__ ""
  | _ -> failwith __LOC__);
  (match {|sig1=:X5spyd6CFnAG5QnDyHfqoSNICd+BUP4LYMz2Q0JXlb//4Ijpzp+kve2w4NIyqeAuM7jTDX+sNalzA8ESSaHD3A==:, proxy_sig=:S6ZzPXSdAMOPjN/6KXfXWNO/f7V6cHm7BXYUh3YD/fRad4BCaRZxP+JH+8XY1I6+8Cy+CM5g92iHgxtRPz+MjniOaYmdkDcnL9cCpXJleXsOckpURl49GwiyUpZ10KHgOEe11sx3G2gxI8S0jnxQB+Pu68U9vVcasqOWAEObtNKKZd8tSFu7LB5YAv0RAGhB8tmpv7sFnIm9y+7X5kXQfi8NMaZaA8i2ZHwpBdg7a6CMfwnnrtflzvZdXAsD3LH2TwevU+/PBPv0B6NMNk93wUs/vfJvye+YuI87HU38lZHowtznbLVdp770I6VHR6WfgS9ddzirrswsE1w5o0LV/g==:|}
         |> Rfc9651.(parse_string ~term:sf_dictionary) with
  | Ok (`Sf_Dictionary
          [(("sig1", []), (`Sf_Binary b0, []));
           (("proxy_sig", []), (`Sf_Binary b1, []))],
        []) -> 
    b0 |> Bytes.length |> check int __LOC__ 64;
    b1 |> Bytes.length |> check int __LOC__ 256
  | Error s -> s |> check string __LOC__ ""
  | _ -> failwith __LOC__);
  ()

let () =
  run
    "seppo_suite" [
    __FILE__ , [
      "set_up",                     `Quick, set_up;
      "tc_b21_example_minimal_rsa", `Quick, tc_b21_example_minimal_rsa;
      "tc_b22",                     `Quick, tc_b22;
      "tc_b23",                     `Quick, tc_b23;
      "tc_b24",                     `Quick, tc_b24;
      "tc_4311",                    `Quick, tc_4311;
    ]
  ]
